//  实现redux部分源码
/**
   preloadedState:初始时的 state
   enhancer:你可以选择指定它以使用第三方功能，如middleware、时间旅行、持久化来增强 store
 */
export const createStore = function createStore(reducer,preloadedState, enhancer) {

    // reducer 必须是一个函数
    if (typeof reducer !== 'function') throw new Error("Expected the root reducer to be a function")

    let state  // 存放公共状态
    let listeners = []  // 事件池

    // 获取公共状态
    const getState = function getState() {
        // 返回公共状态信息即可
        return state
    }

    // 向事件池中加入让组件更新的方法
    const subscribe = function subscribe(listener) {
        // 判断这个lister是不是函数
        if (typeof listener !== 'function') throw new TypeError('Expected the listener to be a function')

        // 把传入的更新组件的方法，存放在事件池中，【需要做去重处理】
        if (!listeners.includes(listener)) {
            listeners.push(listener)
        }

        // 返回一个从事件池中，移除方法的函数
        return function unsubscribe() {
            let index = listeners.indexOf(listener)
            listeners.splice(index, 1)
        }
    }

    // 派发任务通知Reducer执行
    const dispatch = function dispatch(action) {
        // 规则校验，action必须是一个对象，并且里面包含了type这个属性
        if (Object.prototype.toString.call(action) !== '[object Object]') {
            throw new TypeError("Action must be plain objects")
        }
        if (typeof action.type === 'undefined') throw new TypeError("Actions may not have an undefined 'type' property ")

        // 把Reducer执行，传递：公共状态、行为对象,还要接收执行的返回值，替换公共状态    
        state = reducer(state, action)

        // 当状态更改，我们还需要把事件池中的更新组件的方法执行
        listeners.forEach(listener => listener())

        return action
    }

    /* 
       replaceReducer:替换 store 当前用来计算 state 的 reducer。
       这是一个高级 API。只有在你需要实现代码分隔，而且需要立即加载一些 reducer 的时候才可能会用到它。
       在实现 Redux 热加载机制的时候也可能会用到。
    */
    // const replaceReducer = function replaceReducer(){
    // }

    // redux内部会默认进行一次dispatch派发，目的：给公共容器中的状态值赋初始值
    const randomString = () => Math.random().toString(36).substring(7).split('').join('.')
    dispatch({
        // type: Symbol() // 这个值要保证是唯一的,es6中可以直接使用Symbol数据类型
        type: randomString
    })

    // 返回创建的store对象
    return {
        dispatch,
        subscribe,
        getState,
        // replaceReducer
    }
}   
